using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;

namespace ValidationFramework.Tests.Utilities
{
    [TestFixture]
    public class AutoKeyDictionaryTests
    {

		[TestFixture]
		public class Construction
		{

			[Test]
			public void Simple()
			{
				new MockStringDictionary();
			}


			[Test]
			public void Comparer()
			{
				new MockStringDictionary(StringComparer.InvariantCultureIgnoreCase);
			}


			[Test]
			public void CapacityComparer()
			{
				var target = new MockStringDictionary(StringComparer.InvariantCultureIgnoreCase, 1);
				Assert.AreEqual(StringComparer.InvariantCultureIgnoreCase, target.Comparer);
			}

		}

		[TestFixture]
		public class Keys
		{
			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary {2, 4, 9};
			    var keys = target.Keys;

				IEnumerable<string> enumerable = keys;
				var enumerator = enumerable.GetEnumerator();

			    enumerator.MoveNext();
				var current = enumerator.Current;
				Assert.AreEqual("2", current);

				enumerator.MoveNext();
				current = enumerator.Current;
				Assert.AreEqual("4", current);

				enumerator.MoveNext();
				current = enumerator.Current;
				Assert.AreEqual("9", current);

			}
		}

		[TestFixture]
		public class Values
		{
			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary {2, 4, 9};
			    var valueCollection = target.Values;

				IEnumerable<int> enumerable = valueCollection;
				var enumerator = enumerable.GetEnumerator();

			    enumerator.MoveNext();
				var current = enumerator.Current;
				Assert.AreEqual(2, current);

				enumerator.MoveNext();
				current = enumerator.Current;
				Assert.AreEqual(4, current);

				enumerator.MoveNext();
				current = enumerator.Current;
				Assert.AreEqual(9, current);

			}
		}

		[TestFixture]
		public class ContainsKey
		{
			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary {2};
			    Assert.IsTrue(target.ContainsKey("2"));
				Assert.IsFalse(target.ContainsKey("1"));
				Assert.IsFalse(target.ContainsKey("3"));
			}
		}
		[TestFixture]
		public class RemoveKey
		{
			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary {2};
			    Assert.IsTrue(target.ContainsKey("2"));
				Assert.IsTrue(target.RemoveKey("2"));
				Assert.IsFalse(target.ContainsKey("2"));
			}

			[Test]
			[ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Dictionary is read-only.")]
			public void ReadOnly()
			{
				var target = new MockStringDictionary();
				target.SetToReadOnly();
				target.RemoveKey("1");
			}

		}
		[TestFixture]
		public class InternalRemove
		{
			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary {2};
			    Assert.IsTrue(target.ContainsKey("2"));
				Assert.IsTrue(target.InternalRemove("2"));
				Assert.IsFalse(target.ContainsKey("2"));
			}

			[Test]
			public void IgnoreReadOnly()
			{
				var target = new MockStringDictionary();
				target.SetToReadOnly();
				target.InternalRemove("1");
			}

			[Test]
			[ExpectedException(typeof(ArgumentNullException))]
			public void ExceptionNullKey()
			{
				var target = new MockStringDictionary();
				target.InternalRemove(null);
			}

		}

		[TestFixture]
		public class IsReadOnly
		{

			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary();
				Assert.IsFalse(target.IsReadOnly);
				target.SetToReadOnly();
				Assert.IsTrue(target.IsReadOnly);
			}
			[Test]
			public void Interface()
			{
				var target = new MockStringDictionary();
				ICollection<int> collection = target;
				Assert.IsFalse(collection.IsReadOnly);
			}
		}

		[TestFixture]
		public class Add
		{
			[Test]
			[ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Dictionary is read-only.")]
			public void ExceptionReadOnly()
			{
				var target = new MockStringDictionary();
				target.SetToReadOnly();
				target.Add(1);
			}
			[Test]
			public void Interface()
			{
				var target = new MockStringDictionary();
				ICollection<int> collection = target;
				collection.Add(1);
				Assert.IsTrue(target.Contains(1));
			}

		}

		[TestFixture]
		public class Clear
		{

			[Test]
			[ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Dictionary is read-only.")]
			public void ExceptionReadOnly()
			{
				var target = new MockStringDictionary();
				target.SetToReadOnly();
				target.Clear();
			}
			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary {2};
			    Assert.IsTrue(target.Contains(2));
				target.Clear();
				Assert.IsFalse(target.Contains(2));
			}
		}

		[TestFixture]
		public class Remove
		{

			[Test]
			[ExpectedException(typeof(InvalidOperationException), ExpectedMessage = "Dictionary is read-only.")]
			public void ExceptionReadOnly()
			{
				var target = new MockStringDictionary();
				target.SetToReadOnly();
				target.Remove(1);
			}
			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary {3};
			    ICollection<int> collection = target;
				Assert.IsTrue(collection.Remove(3));
				Assert.IsFalse(target.ContainsKey("3"));
				Assert.IsFalse(collection.Remove(3));
			}

			[Test]
			public void NonExisting()
			{
				var target = new MockStringDictionary {1};
			    ICollection<int> collection = target;
				Assert.IsFalse(collection.Remove(2));
			}

		}


		[TestFixture]
		public class GetEnumerator
		{

			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary {2, 4, 9};
			    IEnumerable<int> enumerable = target;
				var enumerator = enumerable.GetEnumerator();

			    enumerator.MoveNext();
				var current = enumerator.Current;
				Assert.AreEqual(2, current);

				enumerator.MoveNext();
				current = enumerator.Current;
				Assert.AreEqual(4, current);

				enumerator.MoveNext();
				current = enumerator.Current;
				Assert.AreEqual(9, current);

			}



			[Test]
			public void Interface()
			{
				var target = new MockStringDictionary {2, 4, 9};
			    IEnumerable enumerable = target;
				var enumerator = enumerable.GetEnumerator();

			    enumerator.MoveNext();
				var current = (int)enumerator.Current;
				Assert.AreEqual(2, current);

				enumerator.MoveNext();
				current = (int)enumerator.Current;
				Assert.AreEqual(4, current);

				enumerator.MoveNext();
				current = (int)enumerator.Current;
				Assert.AreEqual(9, current);

			}


		}


		[TestFixture]
		public class Contains
		{
			[Test]
			public void ContainsTest()
			{
				var target = new MockStringDictionary {2};
			    ICollection<int> collection = target;
				Assert.IsTrue(collection.Contains(2));
				Assert.IsFalse(collection.Contains(1));
				Assert.IsFalse(collection.Contains(3));
			}
		}


		[TestFixture]
		public class CopyTo
		{

			[Test]
			public void Simple()
			{
				var target = new MockStringDictionary {1, 2, 3};
			    ICollection<int> collection = target;
				var pairs = new int[3];
				collection.CopyTo(pairs, 0);
				Assert.AreEqual(1, pairs[0]);
				Assert.AreEqual(2, pairs[1]);
				Assert.AreEqual(3, pairs[2]);
			}
	
		}


    }


    internal class MockStringDictionary : AutoKeyDictionary<string, int>
    {
        public MockStringDictionary()
        {
        }



        public MockStringDictionary(IEqualityComparer<string> comparer)
            : base(comparer)
        {
        }




        public MockStringDictionary(IEqualityComparer<string> comparer, int capacity)
            : base(comparer, capacity)
        {
        }


        protected override string GetKeyForItem(int item)
        {
            return item.ToString();
        }
    }
}